package top.hmtools.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import top.hmtools.io.NioFileTools;

/**
 * MD5算法工具类
 * @author Hybomyth
 * 创建日期：2016-12-11下午4:06:30
 */
public class MD5Tools {

	/**
	 * 获得 字节数组 的MD5加密值，结果为英文字母小写
	 * @param bytes
	 * @return
	 */
	public final static String getLowMD5Str(byte[] bytes) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(bytes);
            // 获得密文
            BigInteger bi = new BigInteger(1, mdInst.digest()); 
            return bi.toString(16);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
	
	/**
	 * 获得 字符串 的MD5加密值，结果为英文字母小写
	 * @param str
	 * @return
	 */
	public final static String getLowMD5Str(String str) {
		return getLowMD5Str(str.getBytes());
	}
	
	/**
	 * 通过NIO读取文件，并计算出其MD5值,结果为英文字母小写
	 * @param file
	 * @return
	 * @throws IOException 
	 */
	public static String getLowMd5ByFileNio(File file) throws IOException{
		byte[] bytesTmp = NioFileTools.readOneFileToByte(file);
		return getLowMD5Str(bytesTmp);
	}
	
	/**
	 * 通过IO读取文件，并计算出其MD5值，结果为英文字母小写
	 * @param file
	 * @return
	 */
	public static String getLowMd5ByFileIo(File file){  
	    String value = null;
	    FileInputStream in = null;
	    try {  
	    	in = new FileInputStream(file);  
	        MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());  
	        MessageDigest md5 = MessageDigest.getInstance("MD5"); 
//	        while(byteBuffer.hasRemaining()){//打印字节码值
//	        	byte b = byteBuffer.get();
//	        	System.out.print(b+" ");
//	        }
//	        byteBuffer.flip();//重置，使其进入输出准备就绪状态
	        md5.update(byteBuffer);  
	        BigInteger bi = new BigInteger(1, md5.digest());  
	        value = bi.toString(16);  
	    } catch (Exception e) {  
	        e.printStackTrace();  
	    } finally {  
            if(null != in) {  
                try {  
                	in.close();  
	            } catch (IOException e) {  
	                e.printStackTrace();  
	            }  
	        }  
	    }  
	    return value;  
    } 
	
	/**
	 * 获取大容量文件的MD5值，结果中的英文字母为小写
	 * @param pathname
	 * @return
	 */
	public static String getLowMd5ByBigFile(String pathname){
		File file = new File(pathname);
		return getLowMd5ByBigFile(file);
	}
	
	/**
	 * 获取大容量文件的MD5值，结果中的英文字母为小写
	 * @param file
	 * @return
	 */
	public static String getLowMd5ByBigFile(File file){
		FileInputStream fileInputStream = null;
        try {
        	MessageDigest mdInst = MessageDigest.getInstance("MD5");
        	fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[8192];
            int length;
            while ((length = fileInputStream.read(buffer)) != -1) {
            	mdInst.update(buffer, 0, length);
            }
            BigInteger bi = new BigInteger(1, mdInst.digest()); 
            return bi.toString(16);
        } catch (FileNotFoundException e) {
        	e.printStackTrace();
            return null;
        } catch (IOException e) {
        	e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		} finally {
            try {
                if (fileInputStream != null)
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
	}
}
